from flask import Flask, url_for,jsonify,abort,current_app
from flask import request, render_template, jsonify,send_from_directory,make_response
from collections import defaultdict
import json
import operator
from functools import reduce
from urllib.parse import quote
from pathlib import Path
import logging
import click
import requests
import json
import pickle
from collections import defaultdict
import re
import utils
from utils import CommandHistory
from extensions import db
from model import PlayHistory

from config import config
 
def create_app(config_name):
    app = Flask(__name__)
    # app.json_encoder = AlchemyEncoder
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)
    return app

app = create_app("production") 
db.init_app(app)

dict_all_tvshows = utils.read_data()
utils.write_oral(dict_all_tvshows)
history = CommandHistory()
debug = False
# debug = True

@app.route('/kodi-siri',methods=["POST"])
def index():
    if not request.is_json:
        return jsonify({"status":"None json data found!"})
    else:
        json_re =request.get_json()
    if not "command" in json_re:
        abort(400)
    command = json_re['command']
    action = utils.parse_command(command)
    # app.logger.debug(f"for {command}: {action} is taken")
    app.logger.debug(u"for {0}: {1} is taken".format(command,action))
    if action == "play":
        result = play(command) 
        if result.json['status'] == True:
            history.push(result.json['play'],action)
            info = utils.parse_play(result.json['play'])
            app.logger.debug("Playing {0}".format(info))
            playhistory = PlayHistory(tvshow=info[0],nseason=info[1],nepisode=info[2])
            db.session.add(playhistory)
            db.session.commit()

    elif action == "next":
        # command = history.get_last_play()
        last_command = get_last_command(command)
        result = playoffset(last_command)
        if result.json['status'] == True:
            history.push(result.json['play'],'play')
            info = utils.parse_play(result.json['play'])
            playhistory = PlayHistory(tvshow=info[0],nseason=info[1],nepisode=info[2])
            db.session.add(playhistory)
            db.session.commit()
        # if command is None:
        #     result = jsonify({'status':False,'play':"之前没有播放记录，请播放后再使用下一集功能"})
        # else:
        #     result = playnext(command)
        #     if result.json['status'] == True:
        #         history.push(result.json['play'],'play')
    elif action == "previous":
        last_command = get_last_command(command)
        result = playoffset(last_command,-1)
        if result.json['status'] == True:
            history.push(result.json['play'],'play')
            info = utils.parse_play(result.json['play'])
            playhistory = PlayHistory(tvshow=info[0],nseason=info[1],nepisode=info[2])
            db.session.add(playhistory)
            db.session.commit()
    elif action == "scan":
        result = scan(command)
    elif action == "stop":
        result = stop()
    elif action == "pause":
        result = pause()
    elif action == "continue":
        result = pause()
    elif action == "showall":
        result = showall()
    elif action == "turnon":
        result = turnon()
    elif action == "turnoff":
        result = turnoff()
    elif action == "setvolume":
        result = setvolume(command)
    elif action == "kodi":
        result = setinput(1)
    elif action == "n1":
        result = setinput(2)
    else:
        result =  jsonify({"status":False,"play":"你的指令无效，要查看有什么电视剧，请说：有什么。要播放某电视剧，请说播放某某某。要暂停播放，请说暂停，要继续播放，请说继续。要退出，请说不看啦","data":json_re})
    return result

@app.cli.command()
@click.option('--drop', is_flag=True, help='Create after drop.')
def initdb(drop):
    """Initialize the database."""
    if drop:
        click.confirm('This operation will delete the database, do you want to continue?', abort=True)
        db.drop_all()
        click.echo('Drop tables.')
    db.create_all()
    click.echo('Initialized database.')

def turnon():
    # turn on tv if tv is off
    status,message = utils.tvturnon()
    return jsonify({"status":status,"play":message})

def turnoff():
    # turn off tv
    status,message = utils.tvturnoff()
    return jsonify({"status":status,"play":message})

def setvolume(command):
    # turn off tv
    status,message = utils.tvsetvolume(command)
    return jsonify({"status":status,"play":message})

def setinput(number):
    # set input hdmi channel
    status,message = utils.tvsetinput(number)
    return jsonify({"status":status,"play":message})


def play(command):
    episodeid,message = utils.get_episodeid(command,dict_all_tvshows)
    if episodeid is not None:
        if debug:
            return jsonify({"status":True,"play":message})
        else:
            result = utils.play_episode(episodeid)
            if result == "OK":
                return jsonify({"status":True,"play":message})
            else:
                return jsonify({"status":False,"play":"播放失败"})
    else:
        return jsonify({"status":False,"play":"播放失败"})


def playoffset(last_command=None,offset=1):
    # if offset is -1: which means previous
        # when using current playing, actually play previous episode
        # when nothing is playing, you want to watch what's left last time, play last episode from where it's left
    # if offset is 1: which means next
    # try to find actual next(from what's playing or what's in the history) and play.

    # using current playing first
    episodeid,message = utils.get_offset_episodeid_from_playing(dict_all_tvshows,offset)
    if episodeid is None:
        # can't get from current playing, get from history
        if last_command is None:
            return jsonify({'status':False,'play':"当前没有播放记录，请播放后再使用下一集或上一集口令,或播放过程中使用"})
        else:
            if offset == -1:
                episodeid,message = utils.get_offset_episodeid(last_command,dict_all_tvshows,0)
            else:
                episodeid,message = utils.get_offset_episodeid(last_command,dict_all_tvshows,offset)
        app.logger.debug("playoffset: for {0} next episode is {1}".format(last_command,message))
        if episodeid is None:
            return jsonify({"status":False,"play":"当前没有播放记录或正在播放的影片，请播放过程中使用或使用看电视播放过一次后使用"})
        else:
            if debug:
                return jsonify({"status":True,"play":message})
            else:
                if offset == -1:
                    result,message_position = utils.play_resume(episodeid)
                else:
                    result = utils.play_episode(episodeid)
                if result == "OK":
                    return jsonify({"status":True,"play":"{0}.{1}".format(message,message_position)})
                else:
                    return jsonify({"status":False,"play":"已找到下一集或上一集，但播放失败"})
    else:
        app.logger.debug("playoffset: for {0} next episode is {1}".format(last_command,message))
        if debug:
            return jsonify({"status":True,"play":message})
        else:
            result = utils.play_episode(episodeid)
            if result == "OK":
                return jsonify({"status":True,"play":message})
            else:
                return jsonify({"status":False,"play":"已找到下一集或上一集，但播放失败"})


def get_last_command(command):
    # get virtual last command from database
    app.logger.debug("get_last_command: command is {0}".format(command))
    tvshow,offset = utils.parse_offset(command)
    app.logger.debug("get_last_command: tvshow is {0}. It's None {1}".format(tvshow,tvshow is None))
    if tvshow is None:
        # no specific tvshow is given
        playhistory = PlayHistory.query.order_by(PlayHistory.id.desc()).first()
        if playhistory is None:
            app.logger.debug("get_last_command: playhistory is None")
            last_command = None
        else:
            last_command = "播放{0}第{1}季第{2}集".format(playhistory.tvshow,playhistory.nseason,playhistory.nepisode)
    else:
        # tvshow is givne
        tvshow = utils.parse_tvshow_name(tvshow)
        playhistory = PlayHistory.query.filter_by(tvshow=tvshow).order_by(PlayHistory.id.desc()).first()
        if playhistory is None:
            last_command = "播放{0}第{1}季第{2}集".format(tvshow,1,1)
        else:
            last_command = "播放{0}第{1}季第{2}集".format(playhistory.tvshow,playhistory.nseason,playhistory.nepisode)
    app.logger.debug("get_last_command: result is {0}".format(last_command))
    return last_command

def scan(command):
    result  = utils.scan_library()
    if result == "OK":
        return jsonify({"status":True})
    else:
        return jsonify({"status":False})

def stop():
    result  = utils.stop_playing()
    if result == "OK":
        return jsonify({"status":True})
    else:
        return jsonify({"status":False})

def pause():
    result  = utils.pause_playing()
    if result == "OK":
        return jsonify({"status":True})
    else:
        return jsonify({"status":False})

def showall():
    allshows = ["{0}({1})".format(ishow,utils.parse_oral_name(ishow)) for ishow in dict_all_tvshows.keys()]
    str_allshows = "\n".join(allshows)
    # return jsonify({"status":True,
    #                 "play":f"当前电视剧有{len(dict_all_tvshows.keys())}部，分别为(括号里是口令)：{str_allshows}"})
    return jsonify({"status":True,
                    "play":"当前电视剧有{0}部，分别为(括号里是口令)：{1}".format(len(dict_all_tvshows.keys()),str_allshows)})

@app.errorhandler(404)
def not_found(error):
    return make_response(jsonify({"error": "Not Found"}),404)

# @app.errorhandler(400)
# def not_found(error):
#     return make_response(jsonify({"error": "post json with command paramerts"}),400)
if __name__ == "__main__":
    app.run(host='0.0.0.0')
    # showall()
